package com.shenhaofeng.app.component;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;

import java.util.ArrayList;
import java.util.List;


/**
 * 如果在{@link android.support.v4.app.Fragment#onActivityResult(int, int, Intent)}中调用
 *{@link Fragment#getChildFragmentManager()}的话，由于StateSaved被标记为true,此时会抛出异常，
 * 而在{@link Activity#onActivityResult(int, int, Intent)}方法中已重新将mStateSaved标记为false,因此无法提交任何事务
 * <p>
 * 在onActivityResult中如果想要显示Fragment会导致抛出异常，因此需要延时该操作。
 * DialogFragment尽量使用Activity的getSupportFragmentManager(),和Fragment的getFragmentManager()
 * </p>
 * <p>
 * Created by 沈豪烽 on 2016/9/13.
 * </p>
 */
public class FragmentTransactionCompat {

    private static final String SAVE_MESSAGES = "FragmentTransactionCompat_messages";


    /**
     * 在onActivityResult中如果想要显示Fragment会导致抛出异常，因此需要延时该操作
     */
    private boolean mDelay;

    private DelayMessages mDelayMessages;

    private OnTransactionHandler onTransactionHandler;


    /**
     * @param onTransactionHandler
     * @param savedInstanceState
     */
    public FragmentTransactionCompat(OnTransactionHandler onTransactionHandler, @Nullable Bundle savedInstanceState) {
        this.onTransactionHandler = onTransactionHandler;
        //恢复延时消息
        if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_MESSAGES)) {
            mDelayMessages = savedInstanceState.getParcelable(SAVE_MESSAGES);
        } else {
            mDelayMessages = new DelayMessages();
        }
    }


    /**
     * 在恢复时，处理延时的操作
     */
    protected void onResumeFragment() {
        mDelay = false;
        int count = mDelayMessages.getMessageCount();
        for (int i = 0; i < count; i++) {
            DelayMessage message=mDelayMessages.get(i);
            mDelayMessages.remove(message);
            onTransactionHandler.handleFragmentDelayMessage(message);
        }

    }


    protected void onFragmentSaveInstanceStateAfter(Bundle outState) {
        mDelay = true;
        outState.putParcelable(SAVE_MESSAGES, mDelayMessages);
    }


    /**
     * 发送一个消息
     */
    public void sendMessage(int tag, Bundle data) {
        if (!mDelay) {
            //如果onFragmentSaveInstanceStateAfter未调用,标识当前仍旧可以提交事务,直接提交处理
            DelayMessage message = new DelayMessage();
            message.tag = tag;
            message.data = data;
            onTransactionHandler.handleFragmentDelayMessage(message);
        } else {
            //反之需要延时处理
            mDelayMessages.addMessage(tag, data);
        }
    }


    /**
     * 延时消息
     */
    public static class DelayMessage implements Parcelable {

        public int tag;

        private Bundle data;


        public DelayMessage() {
        }


        public Bundle getData() {
            if (data == null) {
                data = new Bundle();
            }
            return data;
        }


        @Override
        public int describeContents() {
            return 0;
        }


        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(this.tag);
            dest.writeBundle(this.data);
        }


        protected DelayMessage(Parcel in) {
            this.tag = in.readInt();
            this.data = in.readBundle(getClass().getClassLoader());
        }


        public static final Creator<DelayMessage> CREATOR = new Creator<DelayMessage>() {
            @Override
            public DelayMessage createFromParcel(Parcel source) {
                return new DelayMessage(source);
            }


            @Override
            public DelayMessage[] newArray(int size) {
                return new DelayMessage[size];
            }
        };
    }



    static class DelayMessages implements Parcelable {

        List<DelayMessage> messages = new ArrayList<>();


        public DelayMessages() {
        }


        public void addMessage(int tag, Bundle data) {
            DelayMessage message = new DelayMessage();
            message.tag = tag;
            message.data = data;
            messages.add(message);
        }


        public int getMessageCount() {
            return messages.size();
        }

        protected void remove(DelayMessage delayMessage){
            messages.remove(delayMessage);
        }

        public DelayMessage get(int index) {
            return messages.get(index);
        }


        public void removeMessage(int tag) {
            for (int i = 0; i < messages.size(); i++) {
                DelayMessage message = messages.get(i);
                if (message.tag == tag) {
                    messages.remove(i);
                    return;
                }
            }

        }


        @Override
        public int describeContents() {
            return 0;
        }


        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeTypedList(this.messages);
        }


        protected DelayMessages(Parcel in) {
            this.messages = in.createTypedArrayList(DelayMessage.CREATOR);
        }


        public static final Creator<DelayMessages> CREATOR = new Creator<DelayMessages>() {
            @Override
            public DelayMessages createFromParcel(Parcel source) {
                return new DelayMessages(source);
            }


            @Override
            public DelayMessages[] newArray(int size) {
                return new DelayMessages[size];
            }
        };
    }


}
